home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / MNetsrc.hqx / Mac TCP_IP Source v.33 / slip.c < prev    next >
Text File  |  1989-01-15  |  5KB  |  243 lines

  1. /* Send and receive IP datagrams on serial lines. Compatible with SLIP
  2.  * under Berkeley Unix.
  3.  */
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "iface.h"
  8. #include "ax25.h"
  9. #include "slip.h"
  10. #include "asy.h"
  11. #include "trace.h"
  12. #ifdef MAC
  13. #include "mac.h"
  14. #endif
  15.  
  16. int asy_ioctl();
  17. int kiss_ioctl();
  18. int slip_send();
  19. void doslip();
  20. int asy_output();
  21.  
  22. /* Slip level control structure */
  23. struct slip slip[ASY_MAX];
  24.  
  25. /* Send routine for point-to-point slip
  26.  * This is a trivial function since there is no slip link-level header
  27.  */
  28. int
  29. slip_send(data,interface,gateway,precedence,delay,throughput,reliability)
  30. struct mbuf *data;        /* Buffer to send */
  31. struct interface *interface;    /* Pointer to interface control block */
  32. int32 gateway;            /* Ignored (SLIP is point-to-point) */
  33. char precedence;
  34. char delay;
  35. char throughput;
  36. char reliability;
  37. {
  38.     if(interface == NULLIF){
  39.         free_p(data);
  40.         return -1;
  41.     }
  42.     dump(interface,IF_TRACE_OUT,TRACE_IP,data);
  43.     return (*interface->raw)(interface,data);
  44. }
  45. /* Send a raw slip frame -- also trivial */
  46. int
  47. slip_raw(interface,data)
  48. struct interface *interface;
  49. struct mbuf *data;
  50. {
  51.     /* Queue a frame on the slip output queue and start transmitter */
  52.     return slipq(interface->dev,data);
  53. }
  54. /* Encode a raw packet in slip framing, put on link output queue, and kick
  55.  * transmitter
  56.  */
  57. static int
  58. slipq(dev,data)
  59. int16 dev;        /* Serial line number */
  60. struct mbuf *data;    /* Buffer to be sent */
  61. {
  62.     register struct slip *sp;
  63.     struct mbuf *slip_encode(),*bp;
  64.     void asy_start();
  65.  
  66.     if((bp = slip_encode(data)) == NULLBUF)
  67.         return -1;    
  68.  
  69.     sp = &slip[dev];
  70.     enqueue(&sp->sndq,bp);
  71.     sp->sndcnt++;
  72.     if(sp->tbp == NULLBUF)
  73.         asy_start(dev);
  74.     return 0;
  75. }
  76. /* Start output, if possible, on asynch device dev */
  77. static void
  78. asy_start(dev)
  79. int16 dev;
  80. {
  81.     register struct slip *sp;
  82.  
  83.     if(!stxrdy(dev))
  84.         return;        /* Transmitter not ready */
  85.  
  86.     sp = &slip[dev];
  87.     if(sp->tbp != NULLBUF){
  88.         /* transmission just completed */
  89.         free_p(sp->tbp);
  90.         sp->tbp = NULLBUF;
  91.     }
  92.     if(sp->sndq == NULLBUF)
  93.         return;    /* No work */
  94.  
  95.     sp->tbp = dequeue(&sp->sndq);
  96.     sp->sndcnt--;
  97.     asy_output(dev,sp->tbp->data,sp->tbp->cnt);
  98. }
  99. /* Encode a packet in SLIP format */
  100. static
  101. struct mbuf *
  102. slip_encode(bp)
  103. struct mbuf *bp;
  104. {
  105.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  106.     register char *cp;
  107.     char c;
  108.  
  109.     /* Allocate output mbuf that's twice as long as the packet.
  110.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  111.      */
  112.     lbp = alloc_mbuf(2*len_mbuf(bp) + 2);
  113.     if(lbp == NULLBUF){
  114.         /* No space; drop */
  115.         free_p(bp);
  116.         return NULLBUF;
  117.     }
  118.     cp = lbp->data;
  119.  
  120.     /* Flush out any line garbage */
  121.     *cp++ = FR_END;
  122.  
  123.     /* Copy input to output, escaping special characters */
  124.     while(pullup(&bp,&c,1) == 1){
  125.         switch(uchar(c)){
  126.         case FR_ESC:
  127.             *cp++ = FR_ESC;
  128.             *cp++ = T_FR_ESC;
  129.             break;
  130.         case FR_END:
  131.             *cp++ = FR_ESC;
  132.             *cp++ = T_FR_END;
  133.             break;
  134.         default:
  135.             *cp++ = c;
  136.         }
  137.     }
  138.     *cp++ = FR_END;
  139.     lbp->cnt = cp - lbp->data;
  140.     return lbp;
  141. }
  142. /* Process incoming bytes in SLIP format
  143.  * When a buffer is complete, return it; otherwise NULLBUF
  144.  */
  145. static
  146. struct mbuf *
  147. slip_decode(dev,c)
  148. int16 dev;    /* Slip unit number */
  149. char c;        /* Incoming character */
  150. {
  151.     struct mbuf *bp;
  152.     register struct slip *sp;
  153.  
  154.     sp = &slip[dev];
  155.     switch(uchar(c)){
  156.     case FR_END:
  157.         bp = sp->rbp;
  158.         sp->rbp = NULLBUF;
  159.         sp->rcnt = 0;
  160.         return bp;    /* Will be NULLBUF if empty frame */
  161.     case FR_ESC:
  162.         sp->escaped = 1;
  163.         return NULLBUF;
  164.     }
  165.     if(sp->escaped){
  166.         /* Translate 2-char escape sequence back to original char */
  167.         sp->escaped = 0;
  168.         switch(uchar(c)){
  169.         case T_FR_ESC:
  170.             c = FR_ESC;
  171.             break;
  172.         case T_FR_END:
  173.             c = FR_END;
  174.             break;
  175.         default:
  176.             sp->errors++;
  177.             break;
  178.         }
  179.     }
  180.     /* We reach here with a character for the buffer;
  181.      * make sure there's space for it
  182.      */
  183.     if(sp->rbp == NULLBUF){
  184.         /* Allocate first mbuf for new packet */
  185.         if((sp->rbp1 = sp->rbp = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  186.             return NULLBUF; /* No memory, drop */
  187.         sp->rcp = sp->rbp->data;
  188.     } else if(sp->rbp1->cnt == SLIP_ALLOC){
  189.         /* Current mbuf is full; link in another */
  190.         if((sp->rbp1->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  191.             /* No memory, drop whole thing */
  192.             free_p(sp->rbp);
  193.             sp->rbp = NULLBUF;
  194.             sp->rcnt = 0;
  195.             return NULLBUF;
  196.         }
  197.         sp->rbp1 = sp->rbp1->next;
  198.         sp->rcp = sp->rbp1->data;
  199.     }
  200.     /* Store the character, increment fragment and total
  201.      * byte counts
  202.      */
  203.     *sp->rcp++ = c;
  204.     sp->rbp1->cnt++;
  205.     sp->rcnt++;
  206.     return NULLBUF;
  207. }
  208. /* Process SLIP line I/O */
  209. void
  210. doslip(interface)
  211. struct interface *interface;
  212. {
  213.     char c;
  214.     struct mbuf *bp;
  215.     int16 dev;
  216.     int16 asy_recv();
  217.  
  218.     dev = interface->dev;
  219.     /* Process any pending input */
  220.     while(asy_recv(dev,&c,1) != 0)
  221.         if((bp = slip_decode(dev,c)) != NULLBUF)
  222.             (*slip[dev].recv)(interface,bp);
  223.  
  224.     /* Kick the transmitter if it's idle */
  225.     if(stxrdy(dev))
  226.         asy_start(dev);
  227. }
  228. /* Unwrap incoming SLIP packets -- trivial operation since there's no
  229.  * link level header
  230.  */
  231. void
  232. slip_recv(interface,bp)
  233. struct interface *interface;
  234. struct mbuf *bp;
  235. {
  236.     int ip_route();
  237.  
  238.     /* By definition, all incoming packets are "addressed" to us */
  239.     dump(interface,IF_TRACE_IN,TRACE_IP,bp);
  240.     ip_route(bp,0);
  241. }
  242.  
  243.